package edu.udo.sopra10.chaturaji.gui.util;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.util.LinkedList;

/**
 * Three column LayoutManager that distributions multiple components to the
 * horizontal side of a centered component.
 * 
 * Currently partly broken. (TODO)
 * 
 * @author Patrick Westerhoff
 */
public class ChaturajiGamePanelLayout implements LayoutManager
{
	/**
	 * Center component.
	 */
	public static final String CENTER = "center";
	
	/**
	 * Left column.
	 */
	public static final String LEFT = "left";
	
	/**
	 * Right column.
	 */
	public static final String RIGHT = "right";
	
	private LinkedList<Component> leftComponents;
	private LinkedList<Component> rightComponents;
	private Component centerComponent;
	
	/**
	 * Constructs an empty ChaturajiGamePanelLayout.
	 */
	public ChaturajiGamePanelLayout ()
	{
		this.leftComponents = new LinkedList<Component>();
		this.rightComponents = new LinkedList<Component>();
	}
	
	@Override
	public void addLayoutComponent ( String name, Component comp )
	{
		if ( name.equals( CENTER ) )
		{
			if ( centerComponent != null )
				throw new IllegalArgumentException( "Only one component allowed in the center" );
			
			centerComponent = comp;
		}
		else if ( name.equals( LEFT ) )
			leftComponents.add( comp );
		else if ( name.equals( RIGHT ) )
			rightComponents.add( comp );
		else
			throw new IllegalArgumentException( "invalid constraint" );
	}
	
	@Override
	public void removeLayoutComponent ( Component comp )
	{
		if ( comp == centerComponent )
			centerComponent = null;
		else if ( leftComponents.contains( comp ) )
			leftComponents.remove( comp );
		else if ( rightComponents.contains( comp ) )
			rightComponents.remove( comp );
	}
	
	@Override
	public void layoutContainer ( Container parent )
	{
		// get available width
		Insets insets = parent.getInsets();
		int maxWidth = parent.getWidth() - insets.left - insets.right;
		int maxHeight = parent.getHeight() - insets.top - insets.bottom;
		
		// calculate sizes
		int sideWidth = 0;
		int leftHeight = 0, rightHeight = 0;
		
		for ( Component c : leftComponents )
		{
			Dimension componentSize = c.getPreferredSize();
			leftHeight = componentSize.height;
			sideWidth = Math.max( sideWidth, componentSize.width );
		}
		
		for ( Component c : rightComponents )
		{
			Dimension componentSize = c.getPreferredSize();
			rightHeight = componentSize.height;
			sideWidth = Math.max( sideWidth, componentSize.width );
		}
		
		// calculate margins
		int leftMargin = ( maxHeight - leftHeight ) / ( leftComponents.size() + 1 );
		int rightMargin = ( maxHeight - rightHeight ) / ( rightComponents.size() + 1 );
		
		// set minimum width
		maxWidth = Math.max( maxWidth, 2 * sideWidth + centerComponent.getMinimumSize().width );
		
		// distribute center component
		centerComponent.setBounds( sideWidth, 0, maxWidth - 2 * sideWidth, maxHeight );
		
		// TODO: Fix horrible layout bug here; this is partly a workaround
		// specialized to ProportionalLayout.
		sideWidth = ( maxWidth - centerComponent.getPreferredSize().width ) / 2;
		
		//centerComponent.setBounds( sideWidth, 0, centerComponent.getSize().width, centerComponent.getSize().height );


		// distribute components
		leftHeight = leftMargin;
		for ( Component c : leftComponents )
		{
			Dimension componentSize = c.getPreferredSize();
			c.setBounds( sideWidth - componentSize.width, leftHeight, componentSize.width, componentSize.height );
			leftHeight += componentSize.height + leftMargin;
		}
		
		rightHeight = rightMargin;
		for ( Component c : rightComponents )
		{
			Dimension componentSize = c.getPreferredSize();
			c.setBounds( maxWidth - sideWidth, rightHeight, componentSize.width, componentSize.height );
			rightHeight += componentSize.height + rightMargin;
		}
	}
	
	@Override
	public Dimension minimumLayoutSize ( Container parent )
	{
		return layoutSize( parent, false );
	}
	
	@Override
	public Dimension preferredLayoutSize ( Container parent )
	{
		return layoutSize( parent, true );
	}
	
	
	/**
	 * Calculates the dimensions needed to layout the visible components
	 * contained in the specified target container.
	 * 
	 * @param parent the container that needs to be laid out.
	 * @param usePreferredSize if the preferred size should be calculated.
	 * @return the dimensions of the container.
	 */
	private Dimension layoutSize ( Container parent, boolean usePreferredSize )
	{
		synchronized ( parent.getTreeLock() )
		{
			Dimension size = new Dimension( centerComponent.getMinimumSize() );
			Dimension d, componentSize;
			
			// left components
			d = new Dimension();
			for ( Component c : leftComponents )
			{
				componentSize = usePreferredSize ? c.getPreferredSize() : c.getMinimumSize();
				d.width = Math.max( d.width, componentSize.width );
				d.height += componentSize.height;
			}
			
			// add left component sizes
			size.width += d.width;
			size.height = Math.max( size.height, d.height );
			

			// right components
			d = new Dimension();
			for ( Component c : rightComponents )
			{
				componentSize = usePreferredSize ? c.getPreferredSize() : c.getMinimumSize();
				d.width = Math.max( d.width, componentSize.width );
				d.height += componentSize.height;
			}
			
			// add right component sizes
			size.width += d.width;
			size.height = Math.max( size.height, d.height );
			
			return d;
		}
	}
	
}
